#!/usr/bin/env python

import sys
import os
import string
import gobject
import time, traceback

import lib.opengl as opengl
from lib.contrlWidgets import *

import pygtk
pygtk.require("2.0")

import gtk
import gtk.glade
import gtk.gtkgl

from soccerbots.core import GUIEvent
from threading import Thread

def thread_safe(func):
    def safe_op(*args):
        try:
            gtk.gdk.threads_enter()
            func(*args)
        except:
            traceback.print_exc(file=sys.stdout)
        finally:
            gtk.gdk.threads_leave()
    return safe_op

class GLArea(gtk.DrawingArea, gtk.gtkgl.Widget):
    def __init__(self, w, h):
        gtk.DrawingArea.__init__(self)
        try:                              
            display_mode = ( gtk.gdkgl.MODE_RGBA | gtk.gdkgl.MODE_DOUBLE | gtk.gdkgl.MODE_DEPTH )
            glconfig = gtk.gdkgl.Config(mode=display_mode)
        except gtk.gdkgl.NoMatches:
            display_mode &= ~gtk.gdkgl.MODE_SINGLE
            glconfig = gtk.gdkgl.Config(mode=display_mode)
        self.set_gl_capability(glconfig)

        self.connect( "expose_event", self.on_expose_event )
        self.connect( "realize", self.on_realize )
        self.connect( "configure_event", self.on_configure_event )

        self.width, self.height = w, h
        opengl.InitGlut()

    def on_configure_event(self, *args):
        gldrawable = self.get_gl_drawable()
        glcontext = self.get_gl_context()
        gldrawable.gl_begin(glcontext)

        # resize
        opengl.InitGL(self.width, self.height)
        opengl.ReSizeGLScene(self.width, self.height)

    def on_realize(self, *args):
        gldrawable = self.get_gl_drawable()
        glcontext = self.get_gl_context()
        if not gldrawable.gl_begin(glcontext): return

        # init
        opengl.InitGL(self.width, self.height)
        opengl.DrawGLScene()

        gldrawable.gl_end()
    
    def on_expose_event(self, *args):
        gldrawable = self.get_gl_drawable()
        glcontext  = self.get_gl_context()
        gldrawable.gl_begin(glcontext)

        # draw
        opengl.DrawGLScene()
        
        gldrawable.swap_buffers()
        gldrawable.gl_end()
 
class SoccerBotsGUI(Thread):
    def exitApp(self):
        sys.exit(0)

    '''When the user close the Window using the X'''
    def on_close(self,event,aux):
        sys.exit(0)
        return True

    '''LOG FINESTRA'''
    def setLogText(self,text):
        self.widgets['statusbar'].pop(1)
        self.widgets['statusbar'].push(1,text)

    '''CLICKS DE LES ACCIONS'''

    def ini_click(self, event):
        if not self.connected:
            self.connected = True
            self.widgets['LBotoIniciar'].set_text('Iniciar')
            self.DisableButtons(['bIniciar','server_addr'])
            self.setLogText("Connectant amb el servidor...")
            e = GUIEvent()
            e.type = GUIEvent.CONNECT
            e.data = self.widgets['server_addr'].get_text()
            self.callback(e)
        else:
            self.setLogText("Iniciant la partida...")
            self.DisableButtons(['bIniciar'])
            e = GUIEvent()
            e.type = GUIEvent.INICI
            self.callback(e)

    def falta_click(self,event):
        self.setLogText("Falta detectada, selecciona el tipus...")
        self.show_frame_faults()
        self.DisableButtons(['bFalta','bGol','bFiPeriode'])

    def gol_click(self,event):
        self.setLogText("Gol de l'equip...")
        e = GUIEvent()
        e.type = GUIEvent.GOAL
        self.callback(e)
        self.hide_frame_faults()
        self.hide_frame_teams()


    def fiperiode_click(self,event):
        self.setLogText("Fi del Periode")
        e = GUIEvent()
        if self.round == 1:
            e.type = GUIEvent.FIPART
            self.DisableButtons(['bFalta','bGol','bFiPeriode'])
            self.EnableButtons(['bIniciar'])
        elif self.round == 2 :
            e.type = GUIEvent.FIPARTIT
            self.DisableButtons(['bFalta','bGol','bFiPeriode'])
        
        self.callback(e)
        self.hide_frame_faults()
        self.hide_frame_teams()

    def FaultFunc(self, TipusFalta, Equip):
        e = GUIEvent()
        e.type = GUIEvent.FAULT
        e.fault = TipusFalta
        e.team = Equip
        self.callback(e)
        self.EnableButtons(['bFalta','bGol','bFiPeriode'])
        self.hide_frame_faults()
        self.hide_frame_teams()

    
    def equip1_click(self,event):
        # FIXME: El equip1 sempre es el "A"??
        self.FaultFunc(self.TipusFalta, GUIEvent.TEAM_A)

    def equip2_click(self,event):
        self.FaultFunc(self.TipusFalta, GUIEvent.TEAM_B)

    def penalti_click(self,event):
        self.setLogText("Un penalti, seleccioni l'equip")
        self.TipusFalta = GUIEvent.PENALTY  
        self.hide_frame_faults()
        self.show_frame_teams()

    def freekick_click(self,event):
        self.setLogText("Un free kick, seleccioni l'equip")
        self.TipusFalta = GUIEvent.FREE_KICK
        self.hide_frame_faults()
        self.show_frame_teams()

    def freeball_click(self,event):
        self.setLogText("Un free ball, seleccioni l'equip")
        self.FaultFunc(GUIEvent.FREE_BALL, GUIEvent.TEAM_A)
        self.hide_frame_faults()
        self.hide_frame_teams()

    '''CLICKS DE LES CAMERAS'''
    def changeCam(self,event):
        if event.get_name() == 'bCamL1':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(0, 0)
        elif event.get_name() == 'bCamL2':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(0, 1)
        elif event.get_name() == 'bCamL3':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(0, 2)
        elif event.get_name() == 'bCamL4':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(0, 3)
        elif event.get_name() == 'bCamL5':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(0, 4)
        elif event.get_name() == 'bCamI1':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(1, 0)
        elif event.get_name() == 'bCamI2':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(1, 1)
        elif event.get_name() == 'bCamI3':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(1, 2)
        elif event.get_name() == 'bCamI4':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(1, 3)
        elif event.get_name() == 'bCamI5':
            self.setLogText("Vols veure la Camera del jugador => %s"%(event.get_label()))
            opengl.SetCamera(1, 4)
        elif event.get_name() == 'bGlobalCamera':
            self.setLogText("Vols veure la Camera Global")
            opengl.SetCamera(-1,-1)
            self.gl_area.on_expose_event(None)
    
    def __init__(self):
        Thread.__init__(self)
        gtk.gdk.threads_init()

        self.round = 1
        self.widgets = Widgets('soccerbots/newgui/gui/soccerbots.glade')
        self.widgets.autoconnect( {
            'on_bIniciar_clicked': self.ini_click,
            'on_bFalta_clicked': self.falta_click,
            'on_bGol_clicked': self.gol_click,
            'on_bFiPeriode_clicked': self.fiperiode_click,
            'on_bEquip1_clicked': self.equip1_click,
            'on_bEquip2_clicked': self.equip2_click,
            'on_bPenalti1_clicked': self.penalti_click,
            'on_bFreeKick1_clicked': self.freekick_click,
            'on_bFreeBall1_clicked': self.freeball_click,
            'on_bCamL1_clicked': self.changeCam,
            'on_bCamL2_clicked': self.changeCam,
            'on_bCamL3_clicked': self.changeCam,
            'on_bCamL4_clicked': self.changeCam,
            'on_bCamL5_clicked': self.changeCam,
            'on_bCamI1_clicked': self.changeCam,
            'on_bCamI2_clicked': self.changeCam,
            'on_bCamI3_clicked': self.changeCam,
            'on_bCamI4_clicked': self.changeCam,
            'on_bCamI5_clicked': self.changeCam,
            'on_bGlobalCamera_clicked': self.changeCam,
            } )

        (w,h) = self.widgets['gl_stuff'].get_size_request()
        self.gl_area = GLArea(w,h)
        self.widgets['gl_stuff'].pack_start(self.gl_area)
        self.widgets['Main'].show_all()
        self.widgets['Main'].connect("delete-event", self.on_close)
        
        self.connected = False
        self.widgets['LBotoIniciar'].set_text("Connectar")
    
        self.DisableButtons(['bFalta','bGol','bFiPeriode'])
        self.hide_frame_faults()
        self.hide_frame_teams()

    def DisableButtons(self, buttons):
        for b in buttons:
            self.widgets[b].set_sensitive(False)

    def EnableButtons(self, buttons):
        for b in buttons:
            self.widgets[b].set_sensitive(True)

    def run(self):
        gtk.main()

    def hide_frame_faults(self):
        self.widgets['frame_fault'].hide()

    def hide_frame_teams(self):
        self.widgets['frame_team'].hide()

    def show_frame_faults(self):
        self.widgets['frame_fault'].show()
    
    def show_frame_teams(self):
        self.widgets['frame_team'].show()

    def SetTime(self, time):
        mins = (time / 1000) / 60
        segs = (time / 1000) % 60
        self.widgets['info_time'].set_text(str(mins) + ':' + str(segs))
    
    def SetScore(self, local, visitant):
        self.widgets['info_counter'].set_text(str(local) + ' - ' + str(visitant))
    
    @thread_safe
    def newState(self, state, start=True):
        if start:
            self.EnableButtons(['bIniciar'])
            self.DisableButtons(['bFalta','bGol','bFiPeriode'])
        else:
            self.DisableButtons(['bIniciar'])
            self.EnableButtons(['bFalta','bGol','bFiPeriode'])

        opengl.SetState(state)
       
        self.SetTime(state.time)
        self.SetScore(state.teamA.goals, state.teamB.goals)
        self.widgets['info_part'].set_text(str(state.round))
        if state.round==1:
            self.widgets['LFinalPeriode'].set_text('Fi Periode')
        elif state.round==2:
            self.widgets['LFinalPeriode'].set_text('Fi Partit')
        self.round = state.round
        self.gl_area.on_expose_event(None)

    def setCallback(self, cb):
        self.callback = cb
